import multiprocessing
import threading
import time
import unittest
from typing import Any

import grpc

from ys_python.proto import MQ_pb2_grpc
from ys_queue import IYSQueue, SimpleYSQueue, GRPCYSQueue


def put_delay(queue: IYSQueue, msg: Any, delay=2):
    time.sleep(delay)
    queue.put(msg)
    print("发送数据")


def get_delay(queue: IYSQueue, delay=2):
    time.sleep(delay)
    queue.get()
    print("接受数据")


class TestSimpleYsQueue(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        cls.msg = {"hi": "这里"}

    def setUp(self) -> None:
        self.queue: IYSQueue = SimpleYSQueue(1, 2)

    def tearDown(self) -> None:
        del self.queue

    def test_put(self):
        """
        验证可以推入数据
        - 队列无数据推入
        - 队列满数据时阻塞推入
        """
        self.queue.put(self.msg)
        self.queue.put(self.msg)

        print("启动获取数据进程")
        _process = multiprocessing.Process(target=get_delay, kwargs={"queue": self.queue})
        _process.start()
        print("阻塞推送")
        self.queue.put(self.msg)
        _process.join()

        print("启动获取数据进程")
        _thread = threading.Thread(target=get_delay, kwargs={"queue": self.queue})
        _thread.start()
        print("阻塞推送")
        self.queue.put(self.msg)
        _thread.join()

    def test_get(self):
        """
        验证可以获取数据
        - 队列有数据, 正常获取数据
        - 队列无数据时阻塞获取数据（进程）
        - 队列无数据时阻塞获取数据（线程）
        """
        self.queue.put(self.msg)
        _msg_get = self.queue.get()
        self.assertDictEqual(self.msg, _msg_get, "数据不一致")

        print("启动推数据进程")
        _process = multiprocessing.Process(target=put_delay, kwargs={"queue": self.queue, "msg": self.msg})
        _process.start()
        print("阻塞接收")
        _msg_get = self.queue.get()
        print("已接受数据")
        self.assertDictEqual(self.msg, _msg_get, "数据不一致")
        _process.join()

        print("启动推数据线程")
        _thread = threading.Thread(target=put_delay, kwargs={"queue": self.queue, "msg": self.msg})
        _thread.start()
        print("阻塞接收")
        _msg_get = self.queue.get()
        print("已接受数据")
        self.assertDictEqual(self.msg, _msg_get, "数据不一致")
        _thread.join()

    def test_try_get(self):
        """
        验证非阻塞获取
        """
        _msg_get = self.queue.try_get()
        self.assertIsNone(_msg_get)

        self.queue.put(self.msg)
        _msg_get = self.queue.try_get()
        self.assertDictEqual(self.msg, _msg_get, "数据不一致")


# GRPC 的测试无法通过自动化测试执行, 这里设计为手动测试模式
if __name__ == '__main__':
    __channel = grpc.insecure_channel('127.0.0.1:10101')
    __stub = MQ_pb2_grpc.MQStub(__channel)
    queue = GRPCYSQueue(0, __stub, "sports.general,weather")

    while True:
        msg = queue.get()
        print("[{}] {}".format(msg.topic, len(msg.message)))

    __channel.close()
